/**
 * Copyright (c) 2010-2020 by skzr.org
 * All rights reserved.
 * @Author <a href="mailto:skzr.org@gmail.com">skzr.org</a>
 * @date 2011-3-14 下午10:40:51
 */
package org.skzr.logging.impl;

import java.text.MessageFormat;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.skzr.logging.ILocalLogger;
import org.skzr.logging.util.UtilSlf4jLocal;
import org.slf4j.Logger;
import org.slf4j.Marker;

/**
 * @author <a href="mailto:skzr.org@gmail.com">skzr.org</a>
 * @version 1.0.0
 * @since JDK1.6
 * @param <T>
 */
public abstract class AbstractLocalLogger<T extends Logger> implements ILocalLogger { // NOPMD by skzrorg on 11-3-15 下午8:23
	/** Map&lt;参数个数, 对应的formatter"[{0}, ..., {n}]"&gt;. */
	private static Map<Integer, String> defaultMsgCache = new ConcurrentHashMap<Integer, String>();
	protected final transient MessageConveyor messageConveyor;
	protected final transient T logger;

	AbstractLocalLogger(T logger, MessageConveyor messageConveyor) {
		this.logger = logger;
		this.messageConveyor = messageConveyor;
	}
	
	/**
	 * 获取缺省消息
	 * @param args 参数
	 * @return "[{0},...,{args.length - 1}]"
	 */
	private String getDefaultMsg(Object[] args) {
		if (args == null) return null;
		final int count = args.length > 0 && args[args.length - 1] instanceof Throwable ? args.length - 1 : args.length;
		if (count == 0) return "[]";
		
		if (!defaultMsgCache.containsKey(count)) {
			StringBuilder buf = new StringBuilder(count * 4 + 2).append("[");
			for (int i = 0; i < count; i++) {
				buf.append('{').append(i).append("}, ");
			}
			buf.setCharAt(buf.length() - 2, ']');
			defaultMsgCache.put(count, buf.substring(0, buf.length() - 1));
		}
		return defaultMsgCache.get(count);
	}
	
	/**
	 * 获取key对应的信息，如果找不到直接使用默认值
	 * @param key 国际化对应key
	 * @param args
	 * @return key对应的国际化文件中的文本
	 */
	protected final String getMessage(Enum<?> key, Object[] args) {
		String text = messageConveyor.getMessage(key);
		return UtilSlf4jLocal.isEmptyStr(text) ? getDefaultMsg(args) : text;
	}
	
	protected static final Throwable getThrowableCandidate(Object[] argArray) {
	    if (argArray == null || argArray.length == 0) return null;
	    final Object lastEntry = argArray[argArray.length - 1];
	    if (lastEntry instanceof Throwable) return (Throwable) lastEntry;
	    return null;
	}

	@Override
	public final String getName() {
		return logger.getName();
	}

	@Override
	public final boolean isDebugEnabled() {
		return logger.isDebugEnabled();
	}

	@Override
	public final boolean isDebugEnabled(Marker marker) {
		return logger.isDebugEnabled(marker);
	}

	@Override
	public final boolean isErrorEnabled() {
		return logger.isErrorEnabled();
	}

	@Override
	public final boolean isErrorEnabled(Marker marker) {
		return logger.isErrorEnabled(marker);
	}

	@Override
	public final boolean isInfoEnabled() {
		return logger.isInfoEnabled();
	}

	@Override
	public final boolean isInfoEnabled(Marker marker) {
		return logger.isInfoEnabled(marker);
	}

	@Override
	public final boolean isTraceEnabled() {
		return logger.isTraceEnabled();
	}

	@Override
	public final boolean isTraceEnabled(Marker marker) {
		return logger.isTraceEnabled(marker);
	}

	public final boolean isWarnEnabled() {
		return logger.isWarnEnabled();
	}

	@Override
	public final boolean isWarnEnabled(Marker marker) {
		return logger.isWarnEnabled(marker);
	}
	
	@Override
	public final String getText(Enum<?> key, Object... args) {
		return MessageFormat.format(getMessage(key, args), args);
	}
	
}
